package com.zonski.jbots.wireless.client;

import com.zonski.jbots.engine.*;
import com.zonski.jbots.game.JBotsConstants;

import java.util.Hashtable;
import java.util.Vector;
import java.io.IOException;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.Sprite;

/**
 * Created by IntelliJ IDEA.
 * User: Chris Glover
 * Date: Oct 29, 2003
 * Time: 9:18:01 AM
 * To change this template use Options | File Templates.
 */
public class RoomRenderer
{
    private static final String[] COLOR_PREFIXES = {"cyan-", "red-", "yellow-", "magenta-"};

    public static final RoomRenderer getRoomRenderer()
        throws IOException
    {
        // loads the default room renderer
        Image tile1 = getImage("/images/tiles/metal-1.png");
        Image tile2 = getImage("/images/tiles/metal-2.png");
        Image tile3 = getImage("/images/tiles/metal-3.png");
        Image tile4 = getImage("/images/tiles/grass-1.png");
        Image tile5 = getImage("/images/tiles/s-grass-1.png");
        Image tile6 = getImage("/images/tiles/w-grass-1.png");
        Image tile7 = getImage("/images/tiles/n-grass-1.png");
        Image tile8 = getImage("/images/tiles/e-grass-1.png");
        Image[] tiles = new Image[]{tile1, tile2, tile3, tile4, tile5, tile6, tile7, tile8};

        RoomRenderer roomRenderer = new RoomRenderer(tiles);

        Image rockImage = getImage("/images/blocks/purple-circle.png");
        Image tempRockImage = getImage("/images/blocks/red-circle.png");
        Image treeImage = getImage("/images/blocks/tree.png");

        roomRenderer.addRenderer(JBotsConstants.ROCK, new SpriteEntityRenderer(rockImage));
        roomRenderer.addRenderer(JBotsConstants.TEMP_ROCK, new SpriteEntityRenderer(tempRockImage));
        roomRenderer.addRenderer(JBotsConstants.TREE, new SpriteEntityRenderer(treeImage));

        Image bombImage1 = getImage("/images/bomb/bomb.png");
        Image bombImage2 = getImage("/images/bomb/bomb-2.png");
        roomRenderer.addRenderer(JBotsConstants.BOMB,
                new SpriteEntityRenderer(new Image[][][]{{{bombImage1}}, null, null, {{bombImage1, bombImage2}}}, 0, 1, false));

        Image chargeImage = getImage("/images/charger/battery.png");
        roomRenderer.addRenderer(JBotsConstants.CHARGE,
                new SpriteEntityRenderer(new Image[][][]{{{chargeImage}}}, 0, 1, false));

        Image capacityImage = getImage("/images/charger/capacity.png");
        roomRenderer.addRenderer(JBotsConstants.CAPACITY,
                new SpriteEntityRenderer(new Image[][][]{{{capacityImage}}}, 0, 1, false));

        roomRenderer.addRenderer(JBotsConstants.LASER, BoundsEntityRenderer.INSTANCE);

        Image[][][] painImages = new Image[][][]{
            null, null,
            getColoredImages("/images/pain/", new String[]{"pain-1.png", "pain-2.png", "pain-3.png"})
        };
        roomRenderer.addRenderer(JBotsConstants.PAIN,
                new SpriteEntityRenderer(painImages, 1, 2, false));

        Image[][][] cometImages = new Image[][][]{
            getColoredImages("/images/comet/", new String[]{"ne-comet.png", "n-comet.png"}),
            getColoredImages("/images/comet/", new String[]{"n-comet-fly.png"})};
        SpriteEntityRenderer cometRenderer = new SpriteEntityRenderer(cometImages, 1, 1, true);
        cometRenderer.setRunToEnd(true);
        roomRenderer.addRenderer(JBotsConstants.COMET, cometRenderer);

        Image[][][] botImages = new Image[][][]{
            getColoredImages("/images/bots/", new String[]{"n-bot.png"}),
            getColoredImages("/images/bots/", new String[]{"n-bot-step4.png", "n-bot-step3.png", "n-bot.png",
                                                           "n-bot-step1.png", "n-bot-step2.png"})
        };
        roomRenderer.addRenderer(JBotsConstants.BOT,
                new SpriteEntityRenderer(botImages, 1, 2, true));

        Image[][][] bombBotImages = new Image[][][]{
            getColoredImages("/images/bombbot/", new String[]{"n-bombbot-1.png"}),
            getColoredImages("/images/bombbot/", new String[]{"n-bombbot-1.png", "n-bombbot-2.png", "n-bombbot-3.png"})
        };
        roomRenderer.addRenderer(JBotsConstants.BOMB_BOT,
                new SpriteEntityRenderer(bombBotImages, 1, 2, true));

        Image[][][] turretBotImages = new Image[][][]{
            getColoredImages("/images/turret/", new String[]{"n-turret.png"})
        };
        roomRenderer.addRenderer(JBotsConstants.TURRET_BOT,
                new SpriteEntityRenderer(turretBotImages, 1, 1, true));

        Image[][][] babyBotImages = new Image[][][]{
            getColoredImages("/images/smasher/", new String[]{"smasher-1.png"}),
            getColoredImages("/images/smasher/",
                    new String[]{"smasher-5.png", "smasher-4.png", "smasher-1.png", "smasher-2.png", "smasher-3.png"})
        };
        roomRenderer.addRenderer(JBotsConstants.BABY_BOT, new SpriteEntityRenderer(babyBotImages, 1, 1, true));

        Image[][] tankBotImages = getColoredImages("/images/tank/", new String[]{"tank-1.png"});
        roomRenderer.addRenderer(JBotsConstants.TANK_BOT,
                new SpriteEntityRenderer(new Image[][][]{tankBotImages, tankBotImages}, 1, 1, true));

        Image[][][] wormBotImages = new Image[][][]{
            getColoredImages("/images/xvert/", new String[]{"xvert1.png"}),
            getColoredImages("/images/xvert/", new String[]{"xvert1.png", "xvert2.png", "xvert3.png"})
        };
        roomRenderer.addRenderer(JBotsConstants.CONVERTER_BOT,
                new SpriteEntityRenderer(wormBotImages, 1, 2, true));

        roomRenderer.addRenderer(JBotsConstants.RECHARGE,
                new SpriteEntityRenderer(new Image[][][]{
                    {{getImage("/images/charger/active.png")}},
                    null,
                    {{getImage("/images/charger/inactive.png")}}
                }, 0, 1, false));

        Image[][][] eggImages = new Image[][][]{
            getColoredImages("/images/egg/",
                    new String[]{"small-egg.png", "medium-egg.png", "medium-egg.png", "large-egg.png"})
        };
        SpriteEntityRenderer eggRenderer = new SpriteEntityRenderer(eggImages, 1, 100, false);
        eggRenderer.setRunToEnd(true);
        roomRenderer.addRenderer(JBotsConstants.EGG, eggRenderer);

        Image[][][] explosionImages = new Image[][][]{
            {{getImage("/images/explosion/explosion0.png"),
              getImage("/images/explosion/explosion1.png"),
              getImage("/images/explosion/explosion2.png"),
              getImage("/images/explosion/explosion3.png"),
              getImage("/images/explosion/explosion4.png"),
              getImage("/images/explosion/explosion5.png")
            }}
        };
        SpriteEntityRenderer explosionRenderer = new SpriteEntityRenderer(explosionImages, 0, 1, false);
        explosionRenderer.setRunToEnd(true);
        roomRenderer.addRenderer(JBotsConstants.EXPLOSION, explosionRenderer);

        return roomRenderer;

    }

    private static final Image getImage(String name)
        throws IOException
    {
        return Image.createImage(name);
    }

    private Hashtable renderers;

    private Image[] tileImages;

    private Image tileImage;

    private Image layer0Image;
    private int layer0Count;

    private Image layer6Image;
    private int layer6Count;
    private boolean cleared = true;

    public RoomRenderer(Image[] tileImages)
    {
        this.renderers = new Hashtable();
        this.tileImages = tileImages;
    }

    public void addRenderer(String entityType, EntityRenderer renderer)
    {
        this.renderers.put(entityType, renderer);
    }

    public final void render(Graphics g, Room room)
    {
        try
        {
            QuickVector layers = room.getLayers();
            drawBackground(g, room, layers);

            for(int i=Math.min(layers.size(), 6); i>1; )
            {
                i--;
                Layer layer = (Layer)layers.elementAt(i);
                drawLayer(g, layer);
            }
        }catch(Exception ex){
            //System.err.println(ex);
            ex.printStackTrace();
        }
    }

    public final Sprite getSprite(String entityType)
    {
        Sprite sprite;
        SpriteEntityRenderer renderer = (SpriteEntityRenderer)this.renderers.get(entityType);
        sprite = renderer.getSprite();
        return sprite;
    }

    private final void drawTiles(Graphics g, Room room)
    {
        int tileSize = room.getTileSize();
        int y = 0;
        for(int i=0; i<room.getNumberOfTilesDown(); i++)
        {
            int x = 0;
            for(int j=0; j<room.getNumberOfTilesAcross(); j++)
            {
                int tileType = room.getTileType(j, i);
                g.drawImage(this.tileImages[tileType], x, y, Graphics.TOP | Graphics.LEFT);
                x += tileSize;
            }
            y += tileSize;
        }
    }

    private final void drawLayer(Graphics g, Layer layer)
    {
        QuickVector entities = layer.getEntities();
        for(int j=entities.size(); j>0; )
        {
            j--;
            Entity entity = (Entity)entities.elementAt(j);
            EntityRenderer renderer = (EntityRenderer)entity.renderer;
            if(renderer == null)
            {
                String entityType = entity.entityType.getName();
                renderer = (EntityRenderer)this.renderers.get(entityType);
                entity.renderer = renderer;
            }
            if(renderer != null)
            {
                renderer.render(g, entity);
            }
        }
    }

    public final void clear()
    {
        this.cleared = true;
    }

    private final void drawBackground(Graphics g, Room room, QuickVector layers)
    {
        Layer layer0 = (Layer)layers.elementAt(0);
        if(this.cleared)
        {
            Image image = Image.createImage(room.getWidth(), room.getHeight());
            Graphics imageGraphics = image.getGraphics();
            this.drawTiles(imageGraphics, room);
            this.tileImage = image;

            createLayer0Image(room, layer0);
            createLayer6Image(room, layers);
            this.cleared = false;
        }else{
            if(this.layer0Count != layer0.getEntities().size())
            {
                createLayer0Image(room, layer0);
                createLayer6Image(room, layers);
            }else{
                int count = 0;
                for(int i=6; i<layers.size(); i++)
                {
                    count += ((Layer)layers.elementAt(i)).getEntities().size();
                }
                if(count != this.layer6Count)
                {
                    createLayer6Image(room, layers);
                }
            }
        }
        g.drawImage(this.layer6Image, 0, 0, Graphics.TOP | Graphics.LEFT);
    }

    private final void createLayer0Image(Room room, Layer layer0)
    {
        Image image = Image.createImage(room.getWidth(), room.getHeight());
        Graphics imageGraphics = image.getGraphics();
        imageGraphics.drawImage(this.tileImage,  0, 0, Graphics.TOP | Graphics.LEFT);
        this.drawLayer(imageGraphics, layer0);
        this.layer0Image = image;
        this.layer0Count = layer0.getEntities().size();
    }

    private final void createLayer6Image(Room room, QuickVector layers)
    {
        int count = 0;
        Image image = Image.createImage(room.getWidth(), room.getHeight());
        Graphics imageGraphics = image.getGraphics();
        imageGraphics.drawImage(this.layer0Image, 0, 0, Graphics.TOP | Graphics.LEFT);
        for(int i=6; i<layers.size(); i++)
        {
            Layer layer = (Layer)layers.elementAt(i);
            this.drawLayer(imageGraphics, layer);
            count += layer.getEntities().size();
        }
        this.layer6Image = image;
        this.layer6Count = count;
    }

    private static Image[][] getColoredImages(String pre, String[] post)
        throws IOException
    {
        Image[][] coloredImages = new Image[COLOR_PREFIXES.length][post.length];
        for(int i=0; i<COLOR_PREFIXES.length; i++)
        {
            String colorPrefix = COLOR_PREFIXES[i];
            for(int j=0; j<post.length; j++)
            {
                Image image = getImage(pre+colorPrefix+post[j]);
                coloredImages[i][j] = image;
            }
        }
        return coloredImages;
    }
}
